<html>
<head><meta charset="utf-8"><title>start/end polling · wg-async-foundations/stream-trait-rfc · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/index.html">wg-async-foundations/stream-trait-rfc</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html">start/end polling</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="224224078"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224224078" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224224078">(Jan 27 2021 at 18:17)</a>:</h4>
<p>Hey <span class="user-mention" data-user-id="250715">@Joshua Barretto</span> -- I was reading your comments on the RFC (I'm catching up here) and I had a few questions. You wrote:</p>
<blockquote>
<p>This also means that there is no longer a natural duality between Stream and Iterator as the RFC claims.</p>
</blockquote>
<p>Just to check I understand, it is correct that this problem is specific to MPMC channels, right? (As <span class="user-mention" data-user-id="295632">@Diggsey</span> <a href="https://github.com/rust-lang/rfcs/pull/2996#issuecomment-763263104">noted here</a>, for example).</p>
<p>In the case of an MPMC <em>synchronous</em> channel, how does this work? You register interest when you call <code>next()</code> and de-register interest when <code>next()</code> returns an item?</p>



<a name="224224968"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224224968" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Joshua Barretto <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224224968">(Jan 27 2021 at 18:22)</a>:</h4>
<p>With a synchronous channel, you always have the guarantee that the thread will be woken up at the end of the waiting period (via unparking in most cases). There's no way to interrupt this process because threads cannot be externally panicked or anything like that (at least, not without obviously invalidating a bunch of invariants).</p>
<p>With futures/streams, there's no such guarantee. Futures and streams are frequently polled partially and then dropped (or just forgotten about for a while). This is true for both, but it's more true for streams where items are commonly extracted one at a time with arbitrary delays between each item.</p>
<p>This fact means that the future/stream must <em>always</em> be ready to never be polled again and this means that optimisations such as 'inboxes' (a location where channel senders can dump items for the receiver to pick up when it wakes) that persist between successive polls are not viable strategies in the async world, leading to less efficient channel implementations.</p>
<p>This is not a problem that's <em>specific</em> to channels, but it is very visible with channels since they act as a shared pool.</p>
<p>Futures are a little more resistant to this problem because they are <em>usually</em> dropped immediately after they stop being polled and so you can add your deregister logic in the <code>Drop</code> impl. This is not the case for streams though since they may often be left to lie around for a long time between successive polls for items.</p>
<p>This 'can-be-dropped-whenever' behaviour of async code is also something that I don't believe is mentioned enough in documentation. It means that unsafe code <em>must</em> return the program to a safe state across all <code>await</code> points since it's an opportunity for the future to be arbitrarily dropped. I imagine that many users of async fail to properly accommodate for this fact when writing async code.</p>



<a name="224227556"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224227556" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224227556">(Jan 27 2021 at 18:39)</a>:</h4>
<p>I see.</p>



<a name="224230293"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224230293" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224230293">(Jan 27 2021 at 18:56)</a>:</h4>
<p>I'm not sure how much the "usually" part matters (i.e., for futures vs streams), but I do see the point you're raising there too.</p>



<a name="224230404"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224230404" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224230404">(Jan 27 2021 at 18:56)</a>:</h4>
<p>That said, it's not clear to me that (e.g.) adding in the calls you mentioned will work -- after all, the stream may be part of some other future or stream that <em>itself</em> is not going to be polled again, right?</p>



<a name="224230461"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224230461" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224230461">(Jan 27 2021 at 18:57)</a>:</h4>
<p>It seems like the problem is kind of "recursive", you ultimately need to propagate that information down</p>



<a name="224230495"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224230495" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224230495">(Jan 27 2021 at 18:57)</a>:</h4>
<p>Perhaps the point is that, in practice, it's a reasonable assumption to assume all futures will be polled again, but it's less true of streams</p>



<a name="224230560"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224230560" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224230560">(Jan 27 2021 at 18:57)</a>:</h4>
<p>Sound correct?</p>



<a name="224233831"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224233831" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Joshua Barretto <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224233831">(Jan 27 2021 at 19:19)</a>:</h4>
<p><span class="user-mention silent" data-user-id="116009">nikomatsakis</span> <a href="#narrow/stream/249502-wg-async-foundations.2Fstream-trait-rfc/topic/start.2Fend.20polling/near/224230495">said</a>:</p>
<blockquote>
<p>Perhaps the point is that, in practice, it's a reasonable assumption to assume all futures will be polled again, but it's less true of streams</p>
</blockquote>
<p>Yes, this is the crux of my point. In the case of streams, it isn't really a recursive issue if users/consumers of the stream (<code>for_each</code>, <code>next</code>, etc.) correctly call the start/stop methods (since their usages just decay to futures which we can sort of assume to have this 'poll-until-completion-or-immediately-drop' property. For this reason, I think there is utility in such methods.</p>



<a name="224243553"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224243553" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224243553">(Jan 27 2021 at 20:35)</a>:</h4>
<p>So <span class="user-mention" data-user-id="295632">@Diggsey</span>, I think, mentioned starting a task to do some of this work.</p>



<a name="224254957"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224254957" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthias247 <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224254957">(Jan 27 2021 at 22:04)</a>:</h4>
<blockquote>
<p>'inboxes' (a location where channel senders can dump items for the receiver to pick up when it wakes) that persist between successive polls are not viable strategies in the async world, leading to less efficient channel implementations.</p>
</blockquote>
<p>This is actually implemented in futures-intrusive mpmc channels (which can be  unbuffered). You are right that it's not as efficient as a synchronous channel, but this is mostly due to extra synchronization being required due to the fact that any async function can be cancelled at any point, which requires the need to unregister resources in an atomic/synchronized fashion</p>



<a name="224311701"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224311701" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224311701">(Jan 28 2021 at 11:09)</a>:</h4>
<p><span class="user-mention" data-user-id="204219">@Matthias247</span> is the strategy there that messages get moved to another inbox when a future is cancelled?</p>



<a name="224437493"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start/end%20polling/near/224437493" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthias247 <a href="https://rust-lang.github.io/zulip_archive/stream/249502-wg-async-foundations/stream-trait-rfc/topic/start.2Fend.20polling.html#224437493">(Jan 29 2021 at 07:16)</a>:</h4>
<p><span class="user-mention" data-user-id="116009">@nikomatsakis</span> the strategy is that the value stays inside the senders state („inbox“) - which is actually the send <code>Future</code> - and gets only moved when a receiver polls. Since this operation can’t be aborted after the poll finished, the value is guaranteed to either be transmitted to stay inside the send future. If sending is aborted the value can be extracted from the send future.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>